// -*-mode:c++; coding:utf-8-*-

#include <ostream>

#include <boost/foreach.hpp>

#include "logger.hpp"

#include "async_module_base.hpp"
#include "async_module_stats.hpp"

namespace xbase
{
	static async_module_stats async_module_stats_instance;
	async_module_stats *async_module_stats::s_async_module_stats = NULL;
	
	void async_module_stats::enable() {
		s_async_module_stats = &async_module_stats_instance;
	}

	void async_module_stats::disable() {
		s_async_module_stats = NULL;
	}

	void async_module_stats::construction(const async_module *module) {
		if(s_async_module_stats == NULL)
			return;
		
		boost::mutex::scoped_lock lock(s_async_module_stats->m_mutex);
		const char *name = module->name();
		info_map::iterator it = s_async_module_stats->m_info.find(name);
		if(it == s_async_module_stats->m_info.end())
		{
			std::pair<info_map::iterator, bool> ret =
				s_async_module_stats->m_info.insert(
					info_map::value_type(name,
							     item())
					);
			LOG_IF((ret.second == false), ERROR,
			       "async module " << name << " insert error");
			it = ret.first;
		}
		if(it != s_async_module_stats->m_info.end())
		{
			it->second.m_total_number++;
			it->second.m_live_number++;
		}
	}
	
	void async_module_stats::destruction(const async_module *module) {
		if(s_async_module_stats == NULL)
			return;
		
		boost::mutex::scoped_lock lock(s_async_module_stats->m_mutex);
		const char *name = module->name();
		const info_map::iterator it = s_async_module_stats->m_info.find(name);
		if(it != s_async_module_stats->m_info.end())
		{
			it->second.m_live_number--;
		}
		else
		{
			LOG(ERROR, "async module " << name << " NOT exists");
		}
	}

	void async_module_stats::print(std::ostream &out) {
		if(s_async_module_stats == NULL)
		{
			out << "async_module_stats not enabled" << std::endl;
			return;
		}
		boost::mutex::scoped_lock lock(s_async_module_stats->m_mutex);
		const char *split_str = " \t ";
		out << "async_module_name" << split_str
		    << "total_number" << split_str
		    << "live_number" << std::endl;
		BOOST_FOREACH(const info_map::value_type &it, s_async_module_stats->m_info)
		{
			out << it.first << split_str
			    << it.second.m_total_number << split_str
			    << it.second.m_live_number
			    << std::endl;
		}
		out << "---------" << std::endl;
		out << "bytes_written = " << s_async_module_stats->m_bytes_written
		    << ", bytes_read = " << s_async_module_stats->m_bytes_read
		    << ", packets_written = " << s_async_module_stats->m_packets_written
		    << ", packets_read = " << s_async_module_stats->m_packets_read
		    << std::endl;
		out << std::endl;
	}

	void async_module_stats::clear() {
		if(s_async_module_stats != NULL)
		{
			boost::mutex::scoped_lock lock(s_async_module_stats->m_mutex);
			s_async_module_stats->m_info.clear();
			s_async_module_stats->m_bytes_written = 0;
			s_async_module_stats->m_bytes_read = 0;
			s_async_module_stats->m_packets_written = 0;
			s_async_module_stats->m_packets_read = 0;
		}
	}
	
} // namespace xbase

